#include <stdio.h>
#include <stdlib.h>
#include "slave.h"
#include <assert.h>
#include "args.h"
#include "aceMesh_utils.h"
#include "aceMesh_task.h"
#include "aceMesh_runtime.h"
#include "helper_slave.h"


__thread_local volatile int buffer_owner[HELPER_BUFFER_COUNT] = {0}; //buffer所有权初始化在主核
volatile struct slave_work_buffer sl_buffers[64][HELPER_BUFFER_COUNT];
volatile void *local_task_top[HELPER_NUM][TOP_WINDOW];
__thread_local int own_buf_idx = 0;
volatile new_slave_table tables[64];
__thread_local_fix int construct_end=0;
volatile int slave_finished[64] = {0}; 
__thread_local volatile int slave_exited = 0;
__thread_local_fix struct latent_top local_top[HELPER_NUM];


// __thread_local struct MemPool slave_pool_ldm;
__thread_local_fix int collision_item_count;

// __uncached volatile int slave_init_done=0;

#define remote_ldm(coreid,ldm_var) ((unsigned long)&ldm_var | ((unsigned long)coreid << 20 ) |(1ULL << 45))
#ifdef ACEMESH_GRAPH_BUILD_PROFILING
#ifdef FINE_PROF
// extern double all_pure_register_time[64];
extern double all_pure_addsucc_time[64];
__thread_local_fix double add_succ_start=0.0;
__thread_local_fix double add_succ_end=0.0;

extern double all_pure_register_time[64];
__thread_local_fix double reg_access_start=0.0;
__thread_local_fix double reg_access_end=0.0;

#endif
extern unsigned long buil_prof[N_BUILD_PROF];
// unsigned long add_succ_start;
#endif

#ifdef FLAT_CONSTRUCT_HELEPR
inline void init_slave_table(int id) {  //初始化
    int i;
    for (i = 0; i < SLAVE_TBL_SIZE; i++) {
        tables[id].items[i].data_addr = NULL;
        tables[id].items[i].data_access =NULL;
        tables[id].items[i].succ = NULL;
    }
    tables[id].col_idx = 0;
    for (i = 0; i < COLLISION_BUF_SIZE; i++) {
        tables[id].col_items[i].data_addr = NULL;
        tables[id].col_items[i].data_access =NULL;
        tables[id].col_items[i].succ = NULL;
    }
}
void init_slave_buffer_and_table(int id) {  //初始化两个buffer的所有权
    int i;
    for (i = 0; i < HELPER_BUFFER_COUNT; i++) {  //buffer数目（HELPER_BUFFER_COUNT）=2
        sl_buffers[id][i].idx = 0;  //idx:当前空位坐标
        buffer_owner[i] = BUF_OWNER_MASTER;  //每个buffer的控制权限初始化在主核
    }

//#ifndef SLAVE_HELPER_WINDOW
    init_slave_table(id);
		printf("哈希表%d初始化完毕\n",id);
//#endif
}
#endif
#ifdef DISTRIBUTE_TOP


void init_localtop_buffer(int id)
{
    // int i;
    // for(i=0;i<NT;i++){
       local_top[id].top_index=0;
       local_top[id].top_task[TOP_WINDOW]=NULL;
    // }
}

#endif
bool task_exists(struct task** array, int size, struct task* task) {  
    for (int i = 0; i < size; i++) {  
        if (array[i]== task) {  
            return true;  
        }  
    }  
    return false;  
}  

void add_succ(struct DataAccess *succ_access, struct DataAccess *pre_access,int id)

{
#if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
    add_succ_start=rtc();
		// unsigned long addsucc_start=rtc();
#endif
     //printf("tbl任务类型%dtblDA地址%p任务地址%ptbl任务地址%p,\n",tbl->data_access->_type,tbl->data_access,data_access->_originator,tbl->data_access->_originator);
    if(pre_access!=NULL){
        if(pre_access->_type==IN && succ_access->_type==IN && pre_access->_accessFlags==SATISFIED){   //识别第一层，前驱是已经就绪的R，新增加剧的R也是自然就绪的，仅连接不阻塞
            slave_set_access_state(SATISFIED, &(succ_access->_accessFlags));
            slave_set_unblock_Successor(pre_access,succ_access); //R1-R2,R1是top，R2为ready
						
#ifdef DISTRIBUTE_TOP
						//数据流地址顺序注册，当前是top后面就不会变为succ
						//将cur_top task发给id+1号从核，让其去识别final top task
					local_top[id].top_task[local_top[id].top_index]=succ_access->_originator;
          local_top[id].top_index++;
#endif  
				//  asm volatile ("memb\n");
					 // printf("不阻塞的前驱子任务%p,后继子任务%p\n",predata_access->_originator,data_access->_originator);
         }else { // 以上三个条件，任一不满足，都说明存在实际的依赖（R-W，W-R，W-W，W-R-R），必须修改引用计数
            slave_setSuccessor(pre_access,succ_access);   
						// asm volatile ("memb\n");
           // printf("前驱子任务%p,后继子任务%p\n",predata_access->_originator,data_access->_originator); 
        }   

    }else{
        if(succ_access->_type==IN){ //该地址没有前驱，且类型为读，则设置addr.top=true
            slave_set_access_state(1, &(succ_access->top));
						// asm volatile ("memb\n");
       // printf("设置%p为top%d\n",data_access,data_access->top);
        }
        slave_set_access_state(SATISFIED, &(succ_access->_accessFlags));
#ifdef DISTRIBUTE_TOP
						//数据流地址顺序注册，当前是top后面就不会变为succ
						//将cur_top task发给id+1号从核，让其去识别final top task
					local_top[id].top_task[local_top[id].top_index]=succ_access->_originator;
          local_top[id].top_index++;

#endif 
}
    //printf("设置succ\n");
#if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
    //  buil_prof[SUB_ADD_SUCC]+=(rtc()-addsucc_start);
		 add_succ_end=rtc();
		all_pure_addsucc_time[_MYID]+=(double)(add_succ_end-add_succ_start)/SFREQ;
#endif
}
#ifndef FLAT_CONSTRUCT_HELEPR
inline struct new_slave_table_item * new_get_collision_buffer_item(struct new_slave_table *addresses)
{
    //printf("addresses->col_idx %d\n",addresses->col_idx );
    assert(addresses->col_idx  < COLLISION_BUF_SIZE);
       if (addresses->col_idx >= COLLISION_BUF_SIZE) {
        int i;
        int empty = 0;
        for (i = 0; i < SLAVE_TBL_SIZE; i++) {
            if (addresses->items[i].data_addr == NULL) {
                empty++;
            }
        }
        printf("empty rate: %f\n", (float)empty / SLAVE_TBL_SIZE);
        fflush(stdout);
        // assert(0);
    }
   struct new_slave_table_item * item = &(addresses->col_items[addresses->col_idx]);
    addresses->col_idx++;
    return item;
}
void helper_reigister_access(struct slave_helper_item *item){

// typedef struct slave_helper_item {  //消息传递五元组
//     volatile void *item_address;
//     volatile struct DataAccess *item_access;
//     volatile struct task *item_task;
//     volatile int type;  
//     volatile int item_id;
// } slave_helper_item;  //依赖域哈希表
		//获取依赖分析需要的各种信息
#ifdef MULZTI_CORE_C
		void *address=item->item_address;
		struct DataAccess *access=item->item_access;
		aceMesh_task *cur_task=(aceMesh_task *)item->item_task;
		int type=item->item_type;
		int id=item->item_id;  //分布式哈希表要用
    slave_initialize(access,type,&(cur_task->task_base),INITED,0);
		unsigned long hash_value = (unsigned long)address * HASH_MULT_VALUE;
		aceMesh_task *parent=slave_getparent(&(cur_task->task_base));
		
#else
		void *address=item->item_address;
		unsigned long hash_value=item->item_hash;
		struct DataAccess *access=item->item_access;
		int id=item->item_id;
		aceMesh_task *cur_task=access->_originator;
		 aceMesh_task *parent=slave_getparent(&(cur_task->task_base));
#endif
		struct DataAccess *predecessor=NULL;

		//当前任务，以及当前复合任务

		//printf("地址%p,子任务%p,父任务%p\n",address,cur_task,parent);
		//复合任务、及对应哈希表
		struct TaskDataAccesses *parentAccessStruct = slave_getDataAccesses(&(parent->task_base));
		volatile struct new_slave_table *addresses = parentAccessStruct->_subaccessBottomMap;

		int tbl_idx = 0;
		//unsigned long hash_value = (unsigned long)address * HASH_MULT_VALUE;
			tbl_idx = ((hash_value) >> 44) & 0xffff; ////取高20位(高位的变化更大)中的低16位，65536
		// printf("%p更新DA地址%ptbl地址%p,\n",tbl->data_access,access->_originator,tbl->data_access->_originator);
		if (addresses->items[tbl_idx].data_addr == address) {  //哈希表存在地址
					predecessor=addresses->items[tbl_idx].data_access;
						slave_add_succ(access, predecessor,id);
							addresses->items[tbl_idx].data_access=access; //更新哈希表
							asm volatile ("memb\n");
				}
				else if (addresses->items[tbl_idx].data_addr == NULL) { //哈希表不存在此地址
						predecessor=addresses->items[tbl_idx].data_access; //NULL
						addresses->items[tbl_idx].data_addr = address;
						slave_add_succ(access, predecessor,id);
						addresses->items[tbl_idx].data_access=access; //更新哈希表
						asm volatile ("memb\n");
				}
				else {
						//printf("哈希冲突%p\n",address);
						struct new_slave_table_item * col_item = NULL;
						struct new_slave_table_item * temp = &(addresses->items[tbl_idx]);
						while (temp->succ != NULL) { 
								//struct new_slave_table_item *temp_item=NULL;
								//temp_item=temp->succ;
								if (temp->succ->data_addr == address) {  
										predecessor=temp->succ->data_access;
										slave_add_succ(access, predecessor,id);
										temp->succ->data_access=access; //更新哈希表
										asm volatile ("memb\n");
										goto update_complete;
								}
								temp = temp->succ;   
						
						}     
						collision_item_count++; 
						col_item = new_get_collision_buffer_item(addresses);    
						temp->succ = col_item;
						col_item->data_addr = address;
						//slave_new_update_hashitem(access, col_item);
						predecessor=col_item->data_access;
						slave_add_succ(access, predecessor,id); //依赖边追加和前驱计数更新
						col_item->data_access=access; //更新哈希表
				update_complete:
						;
			
				}

			// printf("子任务前驱计数task%p,precount:%d\n",cur_task,cur_task->task_base._predecessorCount);
}
#else
inline struct new_slave_table_item * new_get_collision_buffer_item(int id)
{
    //printf("tables[_MYID]->col_idx %d\n",tables[_MYID]->col_idx );
    assert(tables[id].col_idx  < COLLISION_BUF_SIZE);
       if (tables[id].col_idx >= COLLISION_BUF_SIZE) {
        int i;
        int empty = 0;
        for (i = 0; i < SLAVE_TBL_SIZE; i++) {
            if (tables[id].items[i].data_addr == NULL) {
                empty++;
            }
        }
        printf("empty rate: %f\n", (float)empty / SLAVE_TBL_SIZE);
        fflush(stdout);
        // assert(0);
    }
   struct new_slave_table_item * item = &(tables[id].col_items[tables[id].col_idx]);
    tables[id].col_idx++;
    return item;
}
#endif

void worker_help_func()
{
#ifdef DEBUG_PBH
	printf("%dhelper轮询开始\n",_MYID);
  fflush(stdout);

#endif
    int ltid=_MYID%8;
    init_localtop_buffer(ltid); //初始化latenttop
    init_slave_buffer_and_table(_MYID); //初始化哈希表和buffer
		printf("从核%d的哈希表初始完毕\n",_MYID);
		int main_finished = 0;
		slave_work_buffer stack_buf;
		int i;
		int id=_MYID%8;
    // latent_top local_top;
 while (1) { //helper一直轮询

        if (construct_end) {
            main_finished = 1;  
        }
        
        if (buffer_owner[own_buf_idx] == BUF_OWNER_SLAVE) {  //buffer权限此时在从核
            int k = 0;
            slave_helper_item * item = NULL;
            int tbl_idx = 0;
            volatile unsigned long dma_reply = 0;
            athread_get(0, &(sl_buffers[_MYID][own_buf_idx]), &stack_buf, sizeof(slave_work_buffer), (void*)&dma_reply, 0, 0, 0);
            while (dma_reply != 1)
                ;
        
    // #ifdef SLAVE_HELPER_PROF
    //         update_task += stack_buf.idx;
    // #endif

            for (k = 0; k < stack_buf.idx; k++) {
#if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
    reg_access_start=rtc();
		unsigned long add_succ_start=rtc();
#endif
                item = &(stack_buf.items[k]);
                // tbl_idx = ((item->hash_value) >> 44) & 0xffff;  //取高20位中的低16位，65536
					
								void *address=item->item_address;
								unsigned long hash_value=item->item_hash;
								struct DataAccess *access=item->item_access;
								// int id=item->item_id;
								

								aceMesh_task *cur_task=access->_originator;
								//aceMesh_task *parent=slave_getparent(&(cur_task->task_base));
								struct DataAccess *predecessor=NULL;

								//unsigned long hash_value = (unsigned long)address * HASH_MULT_VALUE;
									tbl_idx = ((hash_value) >> 44) & 0xffff; ////取高20位(高位的变化更大)中的低16位，65536
								// printf("%p更新DA地址%ptbl地址%p,\n",tbl->data_access,access->_originator,tbl->data_access->_originator);
								if (tables[_MYID].items[tbl_idx].data_addr == address) {  //哈希表存在地址
											predecessor=tables[_MYID].items[tbl_idx].data_access;
												slave_add_succ(access, predecessor,id);
													tables[_MYID].items[tbl_idx].data_access=access; //更新哈希表
													asm volatile ("memb\n");
										}
										else if (tables[_MYID].items[tbl_idx].data_addr == NULL) { //哈希表不存在此地址
												predecessor=tables[_MYID].items[tbl_idx].data_access; //NULL
												tables[_MYID].items[tbl_idx].data_addr = address;
												slave_add_succ(access, predecessor,id);
												tables[_MYID].items[tbl_idx].data_access=access; //更新哈希表
												asm volatile ("memb\n");
										}
										else {
												//printf("哈希冲突%p\n",address);
												struct new_slave_table_item * col_item = NULL;
												struct new_slave_table_item * temp = &(tables[_MYID].items[tbl_idx]);
												while (temp->succ != NULL) { 
														//struct new_slave_table_item *temp_item=NULL;
														//temp_item=temp->succ;
														if (temp->succ->data_addr == address) {  
																predecessor=temp->succ->data_access;
																slave_add_succ(access, predecessor,id);
																temp->succ->data_access=access; //更新哈希表
																asm volatile ("memb\n");
																goto update_complete;
														}
														temp = temp->succ;   
												
												}     
												collision_item_count++; 
												col_item = new_get_collision_buffer_item(_MYID);    
												temp->succ = col_item;
												col_item->data_addr = address;
												//slave_new_update_hashitem(access, col_item);
												predecessor=col_item->data_access;
												slave_add_succ(access, predecessor,id); //依赖边追加和前驱计数更新
												col_item->data_access=access; //更新哈希表
										update_complete:
												;
									
										}
#if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
    buil_prof[SUB_ADD_SUCC]+=(rtc()-add_succ_start);

    reg_access_end=rtc();
    all_pure_register_time[_MYID]+=(double)(reg_access_end-reg_access_start)/SFREQ;
#endif
            }

            asm volatile ("memb\n");
            buffer_owner[own_buf_idx] = BUF_OWNER_MASTER;  //分析完512个df之后控制权移交主核
            own_buf_idx = (own_buf_idx + 1) % HELPER_BUFFER_COUNT;  //切换下一个buffer
        }
        else {
            if (main_finished) {  //此时主核没有把权限移交给从核，但是主核已经发完所有的数据流消息
             //到达一个窗口
						 volatile unsigned long dma_reply = 0;
               athread_put(0, &(local_top[id]), &local_task_top[id][0], sizeof(latent_top), (void*)&dma_reply, 0, 0);                
								while (dma_reply != 1)
                ;  
								printf("_MYID%d号从核latent_top写入主存完成\n",_MYID);
							slave_finished[_MYID] = 1;
                for (i = 8; i < 8+HELPER_NUM; i++) {  //helper已经全部关闭
                    if (slave_finished[i] == 0) {
                        break;
                    }
                }
                if (i == 8+HELPER_NUM) {

    // #ifdef SLAVE_HELPER_PROF
    //                 for (i = 0; i < SLAVE_TBL_SIZE; i++) {
    //                     if (tables[_MYID].items[i].succ != NULL) {
    //                         collision_slot_count++;
    //                     }
    //                 }
    // #endif

    #ifdef SLAVE_HELPER_WINDOW
                    construct_end = 0;
                    slave_finished[_MYID] = 0;
    #endif
                    slave_exited = 1; 
                    asm volatile ("memb\n");
                    break;
                }
            }
        }

    }   

}
